package com.feifan.web.controller.oa;

import com.feifan.common.constant.ScheduleConstants;
import com.feifan.common.core.controller.BaseController;
import com.feifan.common.core.domain.AjaxResult;
import com.feifan.common.exception.job.TaskException;
import com.feifan.common.utils.DateUtils;
import com.feifan.common.utils.StringUtils;
import com.feifan.framework.util.ShiroUtils;
import com.feifan.oa.domain.Schedule;
import com.feifan.oa.service.IHolidayDateService;
import com.feifan.oa.service.IHolidayWorkingDateService;
import com.feifan.oa.service.ILeaveService;
import com.feifan.oa.service.IScheduleService;
import com.feifan.quartz.domain.SysJob;
import com.feifan.quartz.service.ISysJobService;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * @program: feifan
 * @description 日历
 * @author: 非凡
 * @create: 2020-07-21 20:49
 **/
@Controller
@RequestMapping("/oa/schedule")
public class ScheduleController extends BaseController {
    private String prefix = "oa/schedule";

    @Autowired
    private ISysJobService sysJobService;
    @Autowired
    private IHolidayDateService holidayDateService;
    @Autowired
    private IHolidayWorkingDateService holidayWorkingDateService;
    @Autowired
    private ILeaveService leaveService;
    @Autowired
    private IScheduleService scheduleService;

    /**
     * 通过输入指定日期时间生成cron表达式
     * @param date
     * @return cron表达式
     */
    public static String getCron(Date date) {
        String dateFormat = "ss mm HH dd MM ? yyyy";
        SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
        String formatTimeStr = null;
        if (date != null) {
            formatTimeStr = sdf.format(date);
        }

        return formatTimeStr;
    }

    /**
     * 获取一个时间n分钟后
     * @param date 时间
     * @param time 分钟数
     * @return 日期
     * @throws ParseException
     */
    public static Date getAdvanceTime(Date date, Integer time) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(Calendar.MINUTE, -time);
        return c.getTime();
    }

    /**
     * 判断一个日期是否为整天
     * @param startTime 日程开始时间
     * @param endTime   日程结束时间
     * @return boolear
     */
    public static Boolean isAllDayLong(Date startTime, Date endTime) {
        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;
        // long ns = 1000;
        // 获得两个时间的毫秒时间差异
        long diff = endTime.getTime() - startTime.getTime();
        // 计算差多少天
        long day = diff / nd;
        // 计算差多少小时
        long hour = diff % nd / nh;
        // 计算差多少分钟
        long min = diff % nd % nh / nm;

        //判断是否为整天
        if (day != 0 && hour == 0 && min == 0) {
            return true;
        } else if (day != 0 && hour != 0 && min != 0) {
            return false;
        } else {
            return false;
        }
    }

    /**
     * 跳转日程首页
     * @param mmap
     * @return
     */
    @RequiresPermissions("oa:schedule:view")
    @GetMapping()
    public String schedule(ModelMap mmap) {
        Schedule schedule = new Schedule();
        schedule.setSysUser(ShiroUtils.getSysUser());
        mmap.put("holidayDate", holidayDateService.selectHolidayDateList(null));
        mmap.put("holidayWorking", holidayWorkingDateService.selectHolidayWorkingDateList());
        mmap.put("leave", leaveService.selectLeaveListByUId(ShiroUtils.getUserId()));
        mmap.put("schedule", scheduleService.selectScheduleList(schedule));
        return prefix + "/schedule";
    }

    /**
     * 保存日程
     * @param schedule
     * @return
     */
    @PostMapping("/save")
    @ResponseBody
    public AjaxResult save(Schedule schedule) {
        schedule.setSysUser(ShiroUtils.getSysUser());
        schedule.setAllDay(isAllDayLong(schedule.getStart(), schedule.getEnd()));
        //获取日程开始时间提前之后的时间
        Date advanceTime = getAdvanceTime(schedule.getStart(), schedule.getAdvanceTime());

        //判断提前提提醒时间是否小于当前时间
        if (System.currentTimeMillis() > advanceTime.getTime()) {
            return AjaxResult.warn("提前提醒时间已超过当前时间");
        }


        /**
         * type
         * 0:不不提醒
         * 1:站内提醒
         * 2.邮箱提醒
         * 3.手机提醒
         */


        schedule.setJobId(0L);

        //添加日程时间 定时任务
        if (schedule.getType() != 0) {
            //判断用户是否已绑定提醒方式参数   默认为站内提醒
            String toUser = ShiroUtils.getUserId().toString();
            if (schedule.getType() == 2) {
                if (ShiroUtils.getSysUser().getEmail() == null) {
                    return AjaxResult.warn("请先绑定您的邮箱");
                }
                toUser = ShiroUtils.getSysUser().getEmail();
            } else if (schedule.getType() == 3) {
                if (ShiroUtils.getSysUser().getPhonenumber() == null) {
                    return AjaxResult.warn("请先绑定您的手机号");
                }
                toUser = ShiroUtils.getSysUser().getPhonenumber();
            }

            try {
                SysJob sysJob = new SysJob();
                sysJob.setJobName("日程提醒");
                sysJob.setJobGroup("SCHEDULE");
                sysJob.setInvokeTarget(StringUtils.format("reminders.remind('{}','{}','{}','{}','{}','{}','{}')",
                        schedule.getTitle(),
                        ShiroUtils.getSysUser().getUserName(),
                        toUser,
                        DateUtils.paseDatFormatter(schedule.getStart()),
                        DateUtils.paseDatFormatter(schedule.getEnd()),
                        schedule.getAdvanceTime(),
                        schedule.getType()
                ));
                sysJob.setCronExpression(getCron(advanceTime));
                sysJob.setMisfirePolicy("2");
                sysJob.setConcurrent("0");
                sysJob.setStatus(ScheduleConstants.Status.NORMAL.getValue());
                sysJob.setCreateBy(ShiroUtils.getSysUser().getUserName());
                sysJob.setRemark("用于日程事件的提醒");

                //添加定时任务
                sysJobService.insertJob(sysJob);
                schedule.setJobId(sysJob.getJobId());

                //修改定时任务的调用参数
                sysJob.setJobId(sysJob.getJobId());
                sysJob.setInvokeTarget(StringUtils.format("reminders.remind('{}','{}','{}','{}','{}','{}','{}','{}'," +
                                "'{}')",
                        sysJob.getJobId(),
                        ShiroUtils.getUserId(),
                        ShiroUtils.getSysUser().getUserName(),
                        toUser,
                        schedule.getTitle(),
                        DateUtils.paseDatFormatter(schedule.getStart()),
                        DateUtils.paseDatFormatter(schedule.getEnd()),
                        schedule.getAdvanceTime(),
                        schedule.getType()
                ));

                sysJobService.updateJob(sysJob);
                scheduleService.insertSchedule(schedule);
                return success("操作成功@" + sysJob.getJobId() + "@" + schedule.getId());
            } catch (SchedulerException | TaskException e) {
                return AjaxResult.error("事件添加失败");
            }
        }
        scheduleService.insertSchedule(schedule);
        return success("操作成功@" + schedule.getJobId() + "@" + schedule.getId());
    }

    /**
     * 修改日程
     * @param schedule
     * @return
     */
    @PostMapping("/edit")
    @ResponseBody
    public AjaxResult edit(Schedule schedule) {

        try {
            schedule.setSysUser(ShiroUtils.getSysUser());
            schedule.setAllDay(isAllDayLong(schedule.getStart(), schedule.getEnd()));
            //获取日程开始时间提前之后的时间
            Date advanceTime = getAdvanceTime(schedule.getStart(), schedule.getAdvanceTime());
            //判断提前提提醒时间是否小于当前时间
            if (System.currentTimeMillis() > advanceTime.getTime()) {
                return AjaxResult.warn("提前提醒时间已超过当前时间");
            }

            /**
             * type
             * 0:不不提醒
             * 1:站内提醒
             * 2.邮箱提醒
             * 3.手机提醒
             */


            //判断是否修改为"不提醒"
            if (schedule.getType() == 0) {
                //修改日程表iD删除定时任务
                SysJob sysJob = new SysJob();
                sysJob.setJobId(schedule.getJobId());
                sysJob.setJobGroup("SCHEDULE");
                sysJobService.deleteJob(sysJob);
                schedule.setJobId(0L);
                scheduleService.updateSchedule(schedule);
                return success("操作成功@0");
            } else { //如果不是修改为"不提醒"则修改定时任务
                //判断用户是否已绑定提醒方式参数   默认为站内提醒
                String toUser = ShiroUtils.getUserId().toString();
                if (schedule.getType() == 2) {
                    if (ShiroUtils.getSysUser().getEmail() == null) {
                        return AjaxResult.warn("请先绑定您的邮箱");
                    }
                    toUser = ShiroUtils.getSysUser().getEmail();
                } else if (schedule.getType() == 3) {
                    if (ShiroUtils.getSysUser().getPhonenumber() == null) {
                        return AjaxResult.warn("请先绑定您的手机号");
                    }
                    toUser = ShiroUtils.getSysUser().getPhonenumber();
                }

                SysJob sysJob = new SysJob();
                //如果原先输入的定时任务ID为0则添加不修改
                if (schedule.getJobId() == null || schedule.getJobId() == 0) {
                    System.out.println("进入0");
                    sysJob.setJobName("日程提醒");
                    sysJob.setJobGroup("SCHEDULE");
                    sysJob.setInvokeTarget(StringUtils.format("reminders.remind('{}','{}','{}','{}','{}','{}','{}')",
                            schedule.getTitle(),
                            ShiroUtils.getSysUser().getUserName(),
                            toUser,
                            DateUtils.paseDatFormatter(schedule.getStart()),
                            DateUtils.paseDatFormatter(schedule.getEnd()),
                            schedule.getAdvanceTime(),
                            schedule.getType()
                    ));
                    sysJob.setCronExpression(getCron(advanceTime));
                    sysJob.setMisfirePolicy("2");
                    sysJob.setConcurrent("0");
                    sysJob.setStatus(ScheduleConstants.Status.NORMAL.getValue());
                    sysJob.setCreateBy(ShiroUtils.getSysUser().getUserName());
                    sysJob.setRemark("用于日程事件的提醒");
                    sysJobService.insertJob(sysJob);
                    schedule.setJobId(sysJob.getJobId());

                    scheduleService.updateSchedule(schedule);
                    return success("操作成功@" + sysJob.getJobId());
                } else {
                    System.out.println("进入1");
                    //修改定时任务的调用参数
                    sysJob.setJobId(schedule.getJobId());
                    sysJob.setInvokeTarget(StringUtils.format("reminders.remind('{}','{}','{}','{}','{}','{}','{}'," +
                                    "'{}','{}')",
                            sysJob.getJobId(),
                            ShiroUtils.getUserId(),
                            ShiroUtils.getSysUser().getUserName(),
                            toUser,
                            schedule.getTitle(),
                            DateUtils.paseDatFormatter(schedule.getStart()),
                            DateUtils.paseDatFormatter(schedule.getEnd()),
                            schedule.getAdvanceTime(),
                            schedule.getType()
                    ));
                    sysJob.setStatus(ScheduleConstants.Status.NORMAL.getValue());
                    sysJob.setCronExpression(getCron(advanceTime));
                    sysJobService.updateJob(sysJob);

                    scheduleService.updateSchedule(schedule);
                    return success("操作成功@" + sysJob.getJobId());
                }
            }
        } catch (Exception e) {
            return error("日程事件修改失败");
        }
    }

    /**
     * 删除日程
     * @param id
     * @param jobId
     * @param type
     * @return
     */
    @PostMapping("/remove")
    @ResponseBody
    public AjaxResult remove(String id, String jobId, String type) {
        try {
            //如果提醒类型不等于不提醒并且定时任务id不等于空则执行
            if (Integer.parseInt(type) != 0 && jobId != null) {
                SysJob sysJob = new SysJob();
                sysJob.setJobId(Long.parseLong(jobId));
                sysJob.setJobGroup("SCHEDULE");
                sysJobService.deleteJob(sysJob);
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
            return AjaxResult.error("事件删除失败");
        }
        return toAjax(scheduleService.deleteScheduleById(Long.parseLong(id)));
    }
}
